/*
 ============================================================================
 Name        : Cervent.c
 Author      : Aleksandar Stancic 09/08
 ============================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "portutil/threading.h"
#include "portutil/sockets.h"
#include "cerv/messaging.h"

#include "bootstrap.h"
#include "servent.h"
#include "cerv/location.h"
#include "cerv/logger.h"

#include "misc/iniconfig.h"

float randRangeF(float min, float max)
{
	return ((float)(rand() % 32767) / (float)32767) * (max - min) + min;
}

int main(void)
{
	CUThread *bootstrap = NULL, *servent = NULL;
	CUThread *servThread[100];
	int sid = 0;
	ININode * ini = ini_parseFile("cervent.ini");	// Otvaranje INIja
	int runBS, runSV;
	float multiplier = 1.0f;

	srand(time(0));

	// Inicijalizacija loggera
	l_init(ini_getString(ini, "logging/ip", "127.0.0.1"),
			ini_getInt(ini, "logging/port", 4444),
			ini_getString(ini, "logging/filenamePattern", NULL));

	runBS = ini_getInt(ini, "cervent/runBootstrap", 0);	// Da li pokretati bootstrap?
	runSV = ini_getInt(ini, "cervent/runServent", 0);	// Da li pokretati servente?

	if(ini_getInt(ini, "servent/constant_data", 0))
		multiplier = 0.0f;

	if(runBS) bootstrap = cu_spawnThread(bootstrapInstanceEntry, NULL);		// Pokreni bootstrap

	cu_sleep(ini_getInt(ini, "servent/start_delay", 0) * 1000);		// Delay, ako ga ima, izmedju bootstrapa i servenata

	if(runSV)
	{
		// Fajl sa listom lokacija
		const char * listName = ini_getString(ini, "cervent/serventLocations", NULL);
		if(listName)
		{
			FILE *locList = fopen(listName, "rt");
			if(!locList)
			{
				printf("Servent list \"%s\" not found, servents not starting\n", listName);
				runSV = 0;
			}
			else
			{
				char locBuffer[512];
				int startPort = ini_getInt(ini, "servent/start_port", 10001);
				int count = 0, max = ini_getInt(ini, "cervent/serventThreads", 999);

				// Kreni liniju po liniju i port po port
				while(!feof(locList) && count < max)
				{
					fgets(locBuffer, 512, locList);
					ini_rtrim(locBuffer);
					if(strlen(locBuffer) > 0)
					{
						SVLaunchParams * svlp = (SVLaunchParams*)calloc(1, sizeof(SVLaunchParams));

						svlp->port = startPort + count;
						svlp->locID = ++count;
						strcpy(svlp->location, locBuffer);

						// Odluci se za neku temperaturu
						svlp->amplitude = randRangeF(0.0f, 10.0f);
						svlp->baseTemperature = randRangeF(268.0f, 303.0f);
						svlp->phase = randRangeF(0.0f, 6.28318531f);
						svlp->increment = randRangeF(0.01f, 0.1f) * multiplier;

						// Pokreni servent
						servThread[sid++] = cu_spawnThread(serventInstanceEntry, svlp);
						cu_sleep(500);	// I sacekaj malo prije sljedeceg, da sistem lakse dise
					}
				}

				fclose(locList);
			}
		}
		else
		{
			// Ako nema liste, pokreni samo jedan
			SVLaunchParams * svlp = (SVLaunchParams*)calloc(1, sizeof(SVLaunchParams));
			svlp->locID = 1;
			svlp->port = ini_getInt(ini, "servent/start_port", 10001);
			strcpy(svlp->location, ini_getString(ini, "servent/location", "A,B,C,D,E"));
			servent = cu_spawnThread(serventInstanceEntry, svlp);
		}
	}

	if(runBS) cu_joinThread(bootstrap);		// Sacekaj bootstrap
	if(runSV)	// Sacekaj sve servente
	{
		int i;
		for(i = 0; i < sid; ++i)
			cu_joinThread(servThread[i]);

		cu_joinThread(servent);
	}

	if(!runBS && !runSV)	// Nije ni bilo nista za pokrenuti?
		printf("Nothing to run - check \"cervent.ini\" file.\n");

	// The End
	ini_destroy(ini);
	l_shutdown();
	return 0;
}


